package com.mango.coomb.threads;


import com.mango.coomb.constant.ThreadConst;
import com.mango.coomb.data.IOData;
import com.mango.coomb.enums.AreaClass;
import com.mango.coomb.enums.Modes;
import com.mango.coomb.enums.Status;
import com.mango.coomb.threads.parameter.ThreadParameter;
import com.mango.coomb.threads.parameter.util.ThreadParamUpdateUtil;

import java.util.Random;

public class WriterRead extends Thread {
    private static final Integer[] writerBufferValueArr = ThreadParameter.getWriterBufferValueArr();
    private Status status = Status.NOT_BEGIN;
    private boolean paused=false;

    @Override
    public void run() {
        if (Modes.RANDOM == ThreadParameter.getModeState()) {
            while (ThreadParameter.isWriterReadRunning) {
                while (!this.paused) {
                    int i = ThreadParamUpdateUtil.searchNull(AreaClass.WRITER, null);
                    if (i == ThreadConst.NOT_SEARCH) {
                        this.status = Status.PAUSED;
                        try {
                            synchronized (writerBufferValueArr) {
                                writerBufferValueArr.wait();
                            }
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    } else {
                        this.status = Status.PAUSED;
                        Random random = new Random();
                        Integer value = random.nextInt();
                        synchronized (ThreadParameter.writerBufferLock[i]) {
                            this.status = Status.RUNNING;
                            ThreadParameter.isWriterBufferLockedArr[i] = true;
                            try {
                                Thread.sleep(250L);
                            } catch (InterruptedException e) {
                                throw new RuntimeException(e);
                            }
                            ThreadParamUpdateUtil.updateWriterBufferValueArr(i, value);

                            ThreadParameter.isWriterBufferLockedArr[i] = false;
                            this.status = Status.NOT_BEGIN;
                        }
                        synchronized (writerBufferValueArr) {
                            writerBufferValueArr.notifyAll();
                        }
                    }
                }
//                this.status = Status.PAUSED;
                try {
                    synchronized (ThreadParameter.writerReadLock) {
                        ThreadParameter.writerReadLock.wait();
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
//                Thread.interrupted();
//                this.status = Status.NOT_BEGIN;
            }
        } else {
            while (ThreadParameter.isWriterReadRunning) {
                while (!this.paused) {
                    int i = ThreadParamUpdateUtil.searchNull(AreaClass.WRITER, null);
                    if (i == ThreadConst.NOT_SEARCH) {
                        this.status = Status.PAUSED;
                        try {
                            synchronized (writerBufferValueArr) {
                                writerBufferValueArr.wait();
                            }
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    } else {
                        this.status = Status.PAUSED;
                        Integer value;
                        synchronized (IOData.sourceDataList) {
                            this.status = Status.RUNNING;
                            value = getSourceDataValue();
                            this.status = Status.NOT_BEGIN;
                        }
                        if (value == null) {
                            ThreadParameter.isWriterBufferLockedArr[i] = false;
                            this.status = Status.PAUSED;
                            synchronized (IOData.sourceDataLock) {
                                try {
                                    IOData.sourceDataLock.wait();
                                } catch (InterruptedException e) {
                                    throw new RuntimeException(e);
                                }
                            }
                        } else {
                            this.status=Status.PAUSED;
                            synchronized (ThreadParameter.writerBufferLock[i]) {
                                this.status = Status.RUNNING;
//                                ThreadParameter.isWriterBufferLockedArr[i] = true;
                                try {
                                    Thread.sleep(250L);
                                } catch (InterruptedException e) {
                                    throw new RuntimeException(e);
                                }
                                ThreadParamUpdateUtil.updateWriterBufferValueArr(i, value);
                                ThreadParameter.isWriterBufferLockedArr[i] = false;
                                this.status = Status.NOT_BEGIN;
                            }
                            synchronized (writerBufferValueArr) {
                                writerBufferValueArr.notifyAll();
                            }
                        }

                    }
                }
                //                    readToWriterBuffer(value);
//                this.status = Status.PAUSED;
                try {
                    synchronized (ThreadParameter.writerReadLock) {
                        ThreadParameter.writerReadLock.wait();
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
//                Thread.interrupted();
//                this.status = Status.NOT_BEGIN;
            }
        }
    }

    private Integer getSourceDataValue() {
        Integer value;
        int size = IOData.sourceDataList.size();
        try {
            Thread.sleep(250L);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        if (size > 0) {
            value = IOData.sourceDataList.get(size - 1);
            IOData.sourceDataList.remove(size - 1);
        } else {
            value = null;
        }
        return value;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    public boolean isPaused() {
        return paused;
    }

    public void setPaused(boolean paused) {
        this.paused = paused;
    }
}
